package com.summer.core.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.summer.core.bean.Pager;
import com.summer.core.bean.Pager.OrderType;
import com.summer.core.dao.BaseDao;

/**
 * Dao实现类 - Dao实现类基类
 * 
 * @author Administrator
 * 
 * @param <T>
 * @param <PK>
 */

@Repository
public class BaseDaoImpl<T, PK extends Serializable> implements BaseDao<T, PK> {

	private Class<T> entityClass;
	protected SessionFactory sessionFactory;

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		this.entityClass = null;
		Class c = getClass();
		Type type = c.getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			Type[] parameterizedType = ((ParameterizedType) type)
					.getActualTypeArguments();
			this.entityClass = (Class<T>) parameterizedType[0];
		}
	}

	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	protected Session getSession() {
		// return sessionFactory.openSession();

		Session session;
		try {
			session = sessionFactory.getCurrentSession();
		} catch (Exception e) {
			// e.printStackTrace();
			session = sessionFactory.openSession();
		}
		return session;

	}

	@SuppressWarnings("unchecked")
	public T get(PK id) {
		Assert.notNull(id, "id is required");
		return (T) getSession().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public T load(PK id) {
		Assert.notNull(id, "id is required");
		return (T) getSession().load(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public List<T> get(PK[] ids) {
		Assert.notEmpty(ids, "ids must not be empty");
		String hql = "from " + entityClass.getName()
				+ " as model where model.id in(:ids)";
		return getSession().createQuery(hql).setParameterList("ids", ids)
				.list();
	}

	@SuppressWarnings("unchecked")
	public T get(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		String hql = "from " + entityClass.getName() + " as model where model."
				+ propertyName + " = ?";
		return (T) getSession().createQuery(hql).setParameter(0, value)
				.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	// 自己写的
	public T get(Map<String, String> map) {
		Assert.notEmpty(map, "map must not be empty");
		String hql = "from " + entityClass.getName() + " as model where ";
		Query query = getSession().createQuery(hql);
		for (Entry<String, String> str : map.entrySet()) {
			query.setParameter("model." + str.getKey(), str.getValue());
		}
		return (T) query.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public List<T> getList(String propertyName, Object value) {

		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		String hql = "from " + entityClass.getName() + " as model where model."
				+ propertyName + " = ?";

		return getSession().createQuery(hql).setParameter(0, value).list();
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		String hql = "from " + entityClass.getName();

		return getSession().createQuery(hql).list();
	}

	
	public List<T> getAll(Pager pager) {
		
		Map<String,String> searchMap=pager.getSearchMap();
		Map<String ,String> SearchType=pager.getSearchType();
		String hql = "from " + entityClass.getName()+"where 1=1";
		if (searchMap != null && searchMap.size() > 0) {
			Set<String> key = searchMap.keySet();
			for (Iterator it = key.iterator(); it.hasNext();) {
				String s = (String) it.next();
				String value=searchMap.get(s);
				String type=SearchType.get(s);
				if (type == null)
				hql+=" and "+s+"="+value;
				else if (type.equals("like"))
				hql+=" and "+s+"like'%"+value+"'";
				else if (type.equals("geProperty"))
				hql+=" and "+s+"<"+value;
			}
		}
		return getSession().createQuery(hql).list();
	}
	
	public Long getTotalCount() {
		String hql = "select count(*) from " + entityClass.getName();
		return (Long) getSession().createQuery(hql).uniqueResult();
	}

	public boolean isUnique(String propertyName, Object oldValue,
			Object newValue) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(newValue, "newValue is required");
		if (newValue == oldValue || newValue.equals(oldValue)) {
			return true;
		}
		if (newValue instanceof String) {
			if (oldValue != null
					&& StringUtils.equalsIgnoreCase((String) oldValue,
							(String) newValue)) {
				return true;
			}
		}
		T object = get(propertyName, newValue);
		return (object == null);
	}

	public boolean isExist(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		T object = get(propertyName, value);
		return (object != null);
	}

	@SuppressWarnings("unchecked")
	public PK save(T entity) {
		Assert.notNull(entity, "entity is required");
		return (PK) getSession().save(entity);
	}

	public void update(T entity) {
		Assert.notNull(entity, "entity is required");
		getSession().update(entity);
	}

	public void saveOrupdate(T entity) {
		Assert.notNull(entity, "entity is required");
		getSession().saveOrUpdate(entity);
	}

	public void delete(T entity) {
		Assert.notNull(entity, "entity is required");
		getSession().delete(entity);
	}

	public void delete(PK id) {
		Assert.notNull(id, "id is required");
		T entity = load(id);
		getSession().delete(entity);
	}

	public void delete(PK[] ids) {
		Assert.notEmpty(ids, "ids must not be empty");
		for (PK id : ids) {
			T entity = load(id);
			getSession().delete(entity);
		}
	}

	public void flush() {
		getSession().flush();
	}

	public void clear() {
		getSession().clear();
	}

	public void evict(Object object) {
		Assert.notNull(object, "object is required");
		getSession().evict(object);
	}

	public Pager findByPager(Pager pager) {
		if (pager == null) {
			pager = new Pager();
		}
		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(entityClass);
		return findByPager(pager, detachedCriteria);
	}

	public Pager findByPager(Pager pager, DetachedCriteria detachedCriteria) {
		if (pager == null) {
			pager = new Pager();
		}
		

		Integer pageNumber = pager.getPageNumber();
		Integer pageSize = pager.getPageSize();
		String property = pager.getProperty();
		String keyword = pager.getKeyword();
		String orderBy = pager.getOrderBy();
		OrderType orderType = pager.getOrderType();
		Map searchMap = pager.getSearchMap();
		Map searchType = pager.getSearchType();

	
		Criteria criteria = detachedCriteria
				.getExecutableCriteria(getSession());
		
		if (StringUtils.isNotEmpty(property) && StringUtils.isNotEmpty(keyword)) {
			String propertyString = "";
			if (property.contains(".")) {
				String propertyPrefix = StringUtils.substringBefore(property,
						".");
				String propertySuffix = StringUtils.substringAfter(property,
						".");
				criteria.createAlias(propertyPrefix, "model");
				propertyString = "model." + propertySuffix;
			} else {
				propertyString = property;
			}

			criteria
					.add(Restrictions.like(propertyString, "%" + keyword + "%"));

		}

		// 多项目搜索
		if (searchMap != null && searchMap.size() > 0) {

			Set<String> key = searchMap.keySet();
			for (Iterator it = key.iterator(); it.hasNext();) {
				String propertyString = "";
				String s = (String) it.next();
				if (s.contains(".")) {
					String propertyPrefix = StringUtils.substringBefore(s, ".");
					String propertySuffix = StringUtils.substringAfter(s, ".");
					criteria.createAlias(propertyPrefix, "model");
					propertyString = "model." + propertySuffix;
				} else {
					propertyString = s;
				}
				
				String type = (String) searchType.get(propertyString);
				if(StringUtils.isNotEmpty(searchMap.get(s).toString()))
				{
				if (type == null)
					criteria.add(Restrictions.eq(propertyString, searchMap.get(s).toString()));
				else if (type.equals("like"))
					criteria.add(Restrictions.like(propertyString, "%"
							+ searchMap.get(s).toString() + "%"));
				else if (type.equals("geProperty"))
					criteria.add(Restrictions.gtProperty(searchMap.get(s)
							.toString(), propertyString));
				else if(type.equals("empty"))
				{
					//criteria.add(Restrictions.or(Restrictions.ne(propertyString, null), Property.forName(propertyString).isNull()));
					
					
					criteria.add(Property.forName(propertyString).isNull());
					  

				}}
				//	criteria.add(Restrictions.isEmpty(propertyString));
			}
		}

		Integer totalCount = (Integer) criteria.setProjection(
				Projections.rowCount()).uniqueResult();

		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		if(!pager.isIs_all())
		{
			//查询分页数据 否则查询 全部数据
		criteria.setFirstResult((pageNumber - 1) * pageSize);
		criteria.setMaxResults(pageSize);
		}
		if (StringUtils.isNotEmpty(orderBy) && orderType != null) {
			if (orderType == OrderType.asc) {
				criteria.addOrder(Order.asc(orderBy));
			} else {
				criteria.addOrder(Order.desc(orderBy));
			}
		}
		pager.setTotalCount(totalCount);
		pager.setList(criteria.list());
		return pager;
	}
	
	
	public  List<T> find(String hql) {   
            List<T> list =  getSession().createQuery(hql).list();   
            return list;   
    }     

	

}